package com.renchi.menu.common.page;


import com.renchi.menu.common.util.FastCopy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.persistence.Query;
import java.util.List;

/**
 * 分页工具类
 */
@Component
public class FastPage {

//    private static OrganizationService organizationService;
//
//    /**
//     * 静态注入
//     */
//    public FastPage(OrganizationService organizationService) {
//        FastPage.organizationService = organizationService;
//    }

    /**
     * 获取JPA分页条件
     */
    public static Pageable getPageable(Object entityVo) {
        //若不存在分页 则抛出异常信息
        if (!(entityVo instanceof PageCondition)) {
            throw new RuntimeException(entityVo.getClass().getSimpleName() + "未继承PageCondition，无法获取分页条件。");
        }
        //获取分页条件
        PageCondition pageCondition = (PageCondition) entityVo;
        Integer page = pageCondition.getPage();
        Integer rows = pageCondition.getRows();
        String sidx = pageCondition.getSidx();
        String sord = pageCondition.getSord();
        //处理非法页码
        if (page == null || page < 0) {
            page = 1;
        }
        //处理非法页面大小
        if (rows == null || rows < 0) {
            rows = 10;
        }
        //获取排序信息
        if (!StringUtils.isEmpty(sidx)) {
            return new PageRequest(page - 1, rows, new Sort("desc".equals(sord) ? Sort.Direction.DESC : Sort.Direction.ASC, sidx));
        }
        return new PageRequest(page - 1, rows);
    }

    /**
     * 获取统一分页结果
     */
    public static <V> PageInfo<V> getPageInfo(Page page, Class<V> entityVoClass) {
        int records = (int) page.getTotalElements();
        int pageSize = page.getSize();
        int total = records % pageSize == 0 ? records / pageSize : records / pageSize + 1;

        PageInfo<V> pageInfo = new PageInfo<>();
        pageInfo.setPage(page.getNumber() + 1);//页码
        pageInfo.setPageSize(pageSize);//页面大小
        List pageList = page.getContent();
        pageInfo.setRows(FastCopy.copyList(pageList, entityVoClass));//分页结果
        if (pageList.size() > 0 && pageList.get(0) instanceof Object[]) {
            pageInfo.setRows(FastCopy.copyListByObjectArray(pageList, entityVoClass));//分页结果
        }
        pageInfo.setRecords(records);//总记录数
        pageInfo.setTotal(total);//总页数
        return pageInfo;
    }

    /**
     * 获取List分页结果
     */
    public static <V> PageInfo<V> getListVoPageInfo(List listVo, int pageSize, int page) {
        int records = listVo.size();
        int total = records % pageSize == 0 ? records / pageSize : records / pageSize + 1;
        PageInfo<V> pageInfo = new PageInfo<>();
        pageInfo.setPage(page);//页码
        pageInfo.setPageSize(pageSize);//页面大小
        pageInfo.setRecords(records);//总记录数
        pageInfo.setTotal(total);//总页数
        //结果分页
        if (listVo != null && records > 0) {
            int pageNo = (page - 1) * pageSize;
            if (pageNo + pageSize > records) {
                listVo = listVo.subList(pageNo, records);
            } else {
                listVo = listVo.subList(pageNo, pageNo + pageSize);
            }
        }
        pageInfo.setRows(listVo);//分页结果

        return pageInfo;
    }

    /**
     * 获取JPA查询条件
     */
//    public static <E> Specification<E> getSpecification(Object entityVo, Class<E> entityClass) {
//        return (root, query, cb) -> {
//            try {
//                //拼接查询条件
//                List<Predicate> predicates = new ArrayList<>();
//                E vo = FastCopy.copy(entityVo, entityClass);
//                for (Field field : vo.getClass().getDeclaredFields()) {
//                    field.setAccessible(true);//获取授权
//                    String fieldName = field.getName();
//                    Object fieldValue = field.get(vo);
//                    if (!field.isAnnotationPresent(Transient.class)) {
//                        if (!StringUtils.isEmpty(fieldValue)) {
//                            //开启模糊查询
//                            if (field.isAnnotationPresent(Like.class)) {
//                                Path fieldColumn = root.get(fieldName);
//                                String fieldValuePattern = ("%" + StringUtils.trimWhitespace(String.valueOf(fieldValue)) + "%").toUpperCase();
//                                //开启模糊查询（严格匹配查询、转大写简体查询、转大写繁体查询）
//                                predicates.add(cb.and(cb.or(
//                                        cb.like(cb.upper(fieldColumn), fieldValuePattern),
//                                        cb.like(cb.upper(fieldColumn), FastLocale.getSimplifiedChinese(fieldValuePattern)),
//                                        cb.like(cb.upper(fieldColumn), FastLocale.getTraditionalChinese(fieldValuePattern))
//                                )));
//                            } else if (field.isAnnotationPresent(InOrgChildren.class)) {
//                                List<OrganizationVO> orgs = organizationService.findAllChildren(String.valueOf(fieldValue));
//                                List<String> orgIds = new ArrayList<>();
//                                orgs.forEach(orgVo -> orgIds.add(orgVo.getOrgId()));
//                                if (orgIds.size() > 0) {
//                                    predicates.add(root.get(fieldName).in(orgIds));
//                                }
//                            }
//                            //开启等值查询
//                            else {
//                                predicates.add(cb.equal(root.get(fieldName), fieldValue));
//                            }
//                        } else {
//                            if (field.isAnnotationPresent(Between.class)) {
//                                //获取最小值
//                                Field minField = vo.getClass().getDeclaredField(field.getAnnotation(Between.class).min());
//                                minField.setAccessible(true);
//                                Object minVal = minField.get(vo);
//                                //获取最大值
//                                Field maxField = vo.getClass().getDeclaredField(field.getAnnotation(Between.class).max());
//                                maxField.setAccessible(true);
//                                Object maxVal = maxField.get(vo);
//                                //开启区间查询
//                                if (field.getType().getName().equals("java.util.Date") || field.getType().getName().equals("java.sql.Timestamp")) {
//                                    if (!StringUtils.isEmpty(minVal)) {
//                                        predicates.add(cb.greaterThanOrEqualTo(root.get(fieldName).as(Date.class), (Date) minVal));
//                                    }
//                                    if (!StringUtils.isEmpty(maxVal)) {
//                                        predicates.add(cb.lessThanOrEqualTo(root.get(fieldName).as(Date.class), (Date) maxVal));
//                                    }
//                                }
//                            }
//                        }
//                    }
//                }
//                return cb.and(predicates.toArray(new Predicate[]{}));
//            } catch (Exception ex) {
//                throw new RuntimeException(ex);
//            }
//        };
//    }

    /**
     * 获取JPA分页结果
     */
    public static Page readPage(Query query, Pageable pageable, Query countQuery) {
        query.setFirstResult((int) pageable.getOffset());
        query.setMaxResults(pageable.getPageSize());
        return PageableExecutionUtils.getPage(query.getResultList(), pageable, () -> executeCountQuery(countQuery));
    }

    //计算总数
    private static Long executeCountQuery(Query countQuery) {
        Assert.notNull(countQuery, "TypedQuery must not be null!");

        List<Number> totals = countQuery.getResultList();
        Long total = 0L;
        for (Number number : totals) {
            if (number != null) {
                total += number.longValue();
            }
        }
        return total;
    }
}
